﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using advadev.CanOpen;


namespace advadev.CanOpen.UnitTests
{

    /// <summary>
    /// Represents the synchronization producer service unit tests
    /// </summary>
    [TestClass]
    public class SynchronizationProducerServiceTest : ICanOpenObjectDictionaryContainer
    {

        #region service tests
        /// <summary>
        /// Service test
        /// </summary>
        [TestMethod]
        public void ServiceTest()
        {
            // initialization
            ServiceTimer serviceTimer = new ServiceTimer();
            SynchronizationProducerService testObject = null;

            // test with default time frame size
            testObject = new SynchronizationProducerService(this, serviceTimer);
            testObject.TransferRequired += new ServiceTransferRequiredEventHandler((object sender, ServiceTransferRequiredEventArgs args) =>
            {
            });
            serviceTimer.Start();
            testObject.Start();
            Thread.Sleep(1000);
            testObject.Stop();
            serviceTimer.Stop();
            Thread.Sleep(500);
        }

        // -->> HACK
        static private string timeToLogString(DateTime time)
        {
            long floorTicks = (long)Math.Floor((double)time.Ticks / (double)TimeSpan.TicksPerMillisecond) * TimeSpan.TicksPerMillisecond;
            long microSeconds = ((time.Ticks - floorTicks) / (TimeSpan.TicksPerMillisecond / 1000));
            if (microSeconds == 1000)
            {
                microSeconds = 0;
            }
            // -->> HACK
            //microSeconds = 0;
            // <<-- HACK
            return time.ToLongTimeString() + "." + string.Format("{0:000}", time.Millisecond) + "." + string.Format("{0:000}", microSeconds);
        }
        // <<-- HACK
        #endregion service tests


        #region ICanOpenObjectDictionaryContainer
        /// <summary>
        /// Gets the node id of the can open object dictionary container
        /// </summary>
        byte ICanOpenObjectDictionaryContainer.NodeId
        {
            get
            {
                return 103;
            }
        }

        /// <summary>
        /// Gets the can open object with the given index as can open data field
        /// object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index as data field object or
        /// null
        /// </returns>
        ICanOpenDataFieldObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index)
        {
            return null;
        }

        /// <summary>
        /// Gets the can open object with the given index and sub index as can
        /// open value object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <param name="subIndex">
        /// Sub index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index and sub index as value
        /// object or null
        /// </returns>
        ICanOpenValueObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index, byte subIndex)
        {
            uint nodeId = ((ICanOpenObjectDictionaryContainer)this).NodeId;
            if (index == 0x1005)
            {
                CanOpenUnsigned32 cobIdSynchronizationMessageParameter = new CanOpenUnsigned32(0x1005, 0x00, true, true);
                cobIdSynchronizationMessageParameter.Value = 0x40000000 + nodeId;
                return cobIdSynchronizationMessageParameter;
            }
            if (index == 0x1006)
            {
                CanOpenUnsigned32 communicationCyclePeriodParameter = new CanOpenUnsigned32(0x1006, 0x00, true, true);
                communicationCyclePeriodParameter.Value = 1000;
                return communicationCyclePeriodParameter;
            }
            if (index == 0x1019)
            {
                CanOpenUnsigned32 synchronousCounterOverflowValueParameter = new CanOpenUnsigned32(0x1019, 0x00, true, true);
                synchronousCounterOverflowValueParameter.Value = 240;
                return synchronousCounterOverflowValueParameter;
            }
            return null;
        }
        #endregion ICanOpenObjectDictionaryContainer

    }

}
